package com.campus.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.campus.entity.Library.LibrarySeat;
import com.campus.entity.Library.LibraryUsage;
import com.campus.entity.ResultBody;
import com.campus.mapper.LibraryUsageMapper;
import com.campus.service.LibrarySeatService;
import com.campus.mapper.LibrarySeatMapper;
import com.campus.util.RedisMutex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.*;

/**
* @author LuTanhang
* @description 针对表【library_seat】的数据库操作Service实现
* @createDate 2023-02-25 18:32:11
*/
@Service
public class LibrarySeatServiceImpl extends ServiceImpl<LibrarySeatMapper, LibrarySeat>
implements LibrarySeatService{

    @Autowired
    private LibrarySeatMapper librarySeatMapper;
    @Autowired
    private LibraryUsageMapper libraryUsageMapper;
    @Autowired
    private RedisMutex redisMutex;

    @Autowired
    private StringRedisTemplate redisTemplate;

    private final String USED_AND_IS_CURRENT_USER="100001";
    private final String NOT_USED_AND_HAS_OTHER="100002";
    private final String USED_AND_NOT_CURRENT_USER="100003";
    private final String OTHER_USER_RESERVING_SEAT="100004";

    @Override
    public ResultBody allSeat(int floor) {
        List<LibrarySeat> seat1 = librarySeatMapper.selectList(new QueryWrapper<LibrarySeat>().eq("floor", floor).gt("end_time", new Timestamp(System.currentTimeMillis())));
        if (seat1==null) {
            seat1= new ArrayList<>();
        }

        List<LibrarySeat> seat2 = new ArrayList<>();
        Set<String> keys = redisTemplate.keys("mutex:" + floor + ":*");
        for(String key:keys){
            String[] split = key.split(":");
            LibrarySeat seat = new LibrarySeat(floor, Integer.valueOf(split[2]), Integer.valueOf(split[3]));
            seat2.add(seat);
        }

        Map<String,List<LibrarySeat>> seats = new HashMap<>();
        seats.put("use",seat1);
        seats.put("reverse",seat2);

        return ResultBody.ok().data("msg",seats);
    }

    @Override
    public ResultBody addSeat(LibraryUsage usage) {
        Integer floor = usage.getFloor();
        Integer rows = usage.getRows();
        Integer column = usage.getColumn();
        String accountId = usage.getAccount();
        String key = "mutex:"+floor+":"+rows+":"+column;
        if (!Objects.equals(redisTemplate.opsForValue().get(key),accountId)){
            return ResultBody.error().data("msg",OTHER_USER_RESERVING_SEAT);
        }
        int insert = libraryUsageMapper.insert(usage);
        LibrarySeat seat = librarySeatMapper.selectOne(new QueryWrapper<LibrarySeat>().eq("floor", floor).eq("lib_rows", rows).eq("lib_cols",column));
        seat.setAccount(usage.getAccount());
        seat.setEndTime(usage.getEndUsage());
        librarySeatMapper.updateById(seat);
        redisMutex.delMutex(floor,rows,column);
        if(insert==0){
            return ResultBody.error().data("msg","100005");
        }

        return ResultBody.ok();
    }


    @Override
    public ResultBody checkSeat(String account, Integer floor, Integer rows, Integer column) {
        if(!redisMutex.setMutex(floor,rows,column,account)){
            return ResultBody.error().data("msg",OTHER_USER_RESERVING_SEAT);
        }
        LibrarySeat seat = librarySeatMapper.selectOne(new QueryWrapper<LibrarySeat>().eq("floor", floor).eq("lib_rows", rows).eq("lib_cols",column));
        if (seat==null){
            return ResultBody.error().data("msg","100006");
        }
        //如果位置未预定，并且用户在其他地方预定了位置
        //如果位置未预定，并且用户没有在其他地方预定了位置
        //如果位置已经预定，并且预定的人不是当前用户
        //如果位置已经预定，并且预定的人是当前用户
        //四种情况其中同时发生一种,且只有第四种才是正确情况，其他会触发错误

        //如果座位未预定
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        if (seat.getEndTime().compareTo(timestamp)<0){
            //如果在座位表中预定者字段含有当前用户
            if (librarySeatMapper.selectList(new QueryWrapper<LibrarySeat>().eq("account",account).ge("end_time",timestamp)).size()!=0){
                return ResultBody.error().data("msg",NOT_USED_AND_HAS_OTHER);
            }else{
                //不含有当前用户，唯一合法情况
                return ResultBody.ok();
            }
        }else{
            if (seat.getAccount().equals(account)){
                return ResultBody.error().data("msg",USED_AND_IS_CURRENT_USER);
            }else{
                return ResultBody.error().data("msg",USED_AND_NOT_CURRENT_USER);
            }
        }
    }
}
